package ffte.property

import spinal.core._
import ffte.default.config

/**
 * FFT I/O configuration case class
 *
 * This class defines the input/output bit width configuration parameters
 * for FFT implementations. It provides a mechanism to apply I/O width
 * settings to specific code scopes and components.
 *
 * Configuration Parameters:
 * - inWidth: Input data bit width for FFT computations
 * - outWidth: Output data bit width for FFT computations
 *
 * Usage Pattern:
 * - I/O configurations can be applied to specific code blocks using .on{} or .apply{}
 * - Uses SpinalHDL's ScopeProperty for hierarchical configuration management
 * - Default values are provided by the global configuration system
 * - Essential for managing precision across FFT pipeline stages
 *
 * @param inWidth Input data bit width (bits per complex component)
 * @param outWidth Output data bit width (bits per complex component)
 */
case class FFTIOConfig(
      inWidth : Int
    , outWidth : Int
){

    /**
     * Apply I/O configuration to a code block
     *
     * Sets this I/O configuration as active within the specified code block
     * and restores the previous configuration afterward.
     *
     * @param body Code block to execute with this I/O configuration
     * @tparam B Return type of the code block
     * @return Result of executing the code block with this I/O configuration
     */
    def on[B](body : => B) = {
        FFTIOProperty(this) on {
            body
        }
    }

    /**
     * Alternative syntax for I/O configuration application
     *
     * Provides a more natural function-call syntax for applying
     * I/O configuration to a code block.
     *
     * @param body Code block to execute with this I/O configuration
     * @tparam B Return type of the code block
     * @return Result of executing the code block with this I/O configuration
     */
    def apply[B](body : => B): B = on(body)
}

/**
 * FFT I/O configuration property manager
 *
 * This object extends SpinalHDL's ScopeProperty to provide hierarchical
 * configuration management for FFT I/O parameters. It allows I/O
 * configurations to be applied to specific scopes and automatically
 * restored when exiting those scopes.
 *
 * Features:
 * - Hierarchical I/O configuration with automatic restoration
 * - Default I/O configuration fallback
 * - Thread-safe configuration management
 * - Integration with SpinalHDL's configuration system
 *
 * Applications:
 * - Managing precision across different FFT stages
 * - Supporting mixed-precision FFT implementations
 * - Enabling component-level I/O width optimization
 */
object FFTIOProperty extends ScopeProperty[FFTIOConfig] {

    /**
     * Default I/O configuration fallback
     *
     * Provides the default I/O configuration values when no specific
     * configuration is active in the current scope.
     */
    override def default: FFTIOConfig = config.DefaultFFTIOConfig
}

/**
 * FFT input width accessor
 *
 * This object provides access to the current FFT input bit width from the
 * active I/O configuration. It serves as a convenient interface for
 * retrieving the input width in FFT component implementations.
 *
 * Usage:
 * ```scala
 * val inputWidth = getFFTIW()
 * ```
 */
object getFFTIW {

    /**
     * Get the current FFT input width
     *
     * Retrieves the input bit width from the active I/O configuration.
     * If no specific configuration is active, returns the default value.
     *
     * @return Current FFT input bit width
     */
    def apply(): Int = FFTIOProperty.get.inWidth
}

/**
 * FFT output width accessor
 *
 * This object provides access to the current FFT output bit width from the
 * active I/O configuration. It serves as a convenient interface for
 * retrieving the output width in FFT component implementations.
 *
 * Usage:
 * ```scala
 * val outputWidth = getFFTOW()
 * ```
 */
object getFFTOW {

    /**
     * Get the current FFT output width
     *
     * Retrieves the output bit width from the active I/O configuration.
     * If no specific configuration is active, returns the default value.
     *
     * @return Current FFT output bit width
     */
    def apply(): Int = FFTIOProperty.get.outWidth
}
